package cn.itsource.hrm.service.impl;

import cn.itsource.hrm.cache.CourseTypeCache;
import cn.itsource.hrm.domain.CourseType;
import cn.itsource.hrm.mapper.CourseTypeMapper;
import cn.itsource.hrm.service.ICourseTypeService;
import cn.itsource.hrm.util.VelocityUtils;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author yhptest
 * @since 2020-06-23
 */
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {

    @Autowired
    private CourseTypeMapper courseTypeMapper;
    @Override
    public List<CourseType> queryTreeData() {
        //        //查询第一级 pid=0
        //        Wrapper<CourseType> wrapper = new EntityWrapper<CourseType>().eq("pid", 0L);
        //        List<CourseType> courseTypes = courseTypeMapper.selectList(wrapper);
        //        //查询第二级 把第一级id作为pid查询第二级
        //        for (CourseType courseType : courseTypes) {
        //            new EntityWrapper<CourseType>().eq("pid", courseType.getId());
        //            List<CourseType> courseTypes2 = courseTypeMapper.selectList(wrapper);
        //        }
        //方案1： 递归获取类型数  不用：以后一个节点就要查询一次儿子 就要发一次sql，节点多了效率低。
        //return queryTreeDataByRecursion(0L);
        //方案2： 循环方案：一次查询出所有节点，再来组织他们关系 只发了一条sql

        //缓存处理
        List<CourseType> treeData = courseTypeCache.loadTreeData();
        System.out.println(treeData);
        if (treeData!=null){
            System.out.println("cache ......");
            return treeData;
        }else{
            System.out.println("db .....");
            List<CourseType> courseTypes = queryTreeDataByLoop(0L);
            courseTypeCache.saveTreeData(courseTypes);
            return courseTypes;
        }



    }

    @Override
    public List<Map<String, Object>> queryTypeCrumbs(Long typeId) {
        List<Map<String,Object>> result = new ArrayList<>();
        //1 通过typeid获取Type进而获取path    .1.2.3.
        CourseType courseType = courseTypeMapper.selectById(typeId);
        String path = courseType.getPath();
        System.out.println(path);
        path = path.substring(1,path.length()-1);  //1.2.3
        //2 通过分隔path得到层次关系数组 【1，2,3】
        String[] paths = path.split("\\.");
        //3 遍历数组 每个节点最终要生成一个Map，包含当前节点自己及其兄弟
        System.out.println(paths);
        for (String idStr : paths) {
            System.out.println(idStr+"jjjjjj");
            Map<String,Object> node = new HashMap<>();
            //3.1 获取自己
            CourseType owerCourseType = courseTypeMapper.selectById(Long.valueOf(idStr));
            node.put("owerCourseType",owerCourseType);
            //2.2 获取兄弟-查询父亲所有儿子再删除自己
            Long pid = owerCourseType.getPid();
            List<CourseType> allChildren = courseTypeMapper
                    .selectList(new EntityWrapper<CourseType>().eq("pid", pid));
            Iterator<CourseType> iterator = allChildren.iterator(); //不能用传统的遍历，一边遍历一边删除，要用迭代器
            while (iterator.hasNext()){
                CourseType courseType1 = iterator.next();
                if (owerCourseType.getId().longValue()==courseType1.getId().longValue()){
                    iterator.remove();
                    break;
                }
            }
            node.put("otherCourseTypes",allChildren);
            result.add(node);
        }
        return result;
    }

    @Autowired
    private CourseTypeCache courseTypeCache;

    //循环方案：一次查询出所有节点，再来组织他们关系 只发了一条sql
    private List<CourseType> queryTreeDataByLoop(long pid) {
        List<CourseType> result = new ArrayList<>();
        //1 获取所有的节点
         List<CourseType> courseTypes = courseTypeMapper.selectList(null);
         //提前建立好id和类型之间一一对应的关系
        Map<Long,CourseType> courseTypeMap = new HashMap<>();
        for (CourseType courseType : courseTypes) {
            courseTypeMap.put(courseType.getId(),courseType);
        }
        //2 遍历所有节点进行处理
        for (CourseType courseType : courseTypes) {
            //2.1 如果是顶级节点之间加入要返回的集合
             if (courseType.getPid().longValue()==pid){
                 result.add(courseType);
             }
             //2.2 作为父亲一个儿子
              else{
                 //2.2.1 获取pid，进而获取父亲
                 Long pidTmp = courseType.getPid();
                 //方案1：循环
                 /*
                 CourseType parent = null;
                 for (CourseType type : courseTypes) {
                     if (pidTmp.longValue()==type.getPid()){
                         parent = type;
                         break;
                     }

                 }*/
                 //方案2：提前建立好对应关系，直接获取
                 CourseType parent = courseTypeMap.get(pidTmp);
                 //2.2.2 parent.getchildren.add(owrer)
                 parent.getChildren().add(courseType);
             }
        }

        return result;

    }

    /**
     * 方案1： 递归获取类型数  不用：以后一个节点就要查询一次儿子 就要发一次sql，节点多了效率低。
     * @return
     */
    private List<CourseType> queryTreeDataByRecursion(Long pid) {
        Wrapper<CourseType> wrapper = new EntityWrapper<CourseType>().eq("pid", pid);
        List<CourseType> courseTypes = courseTypeMapper.selectList(wrapper);
        //没有儿子就可以返回
        if (courseTypes==null || courseTypes.size()<1)
              return null;

        for (CourseType courseType : courseTypes) {
            Long pidTmp = courseType.getId();
            List<CourseType> children = queryTreeDataByRecursion(pidTmp);
            courseType.setChildren(children);
        }
        //无论如何最终都要返回
        return courseTypes;
    }


    //缓存需要同步更新  删除缓存，以后它再次查询的时候重新获取获取
    //双写一致性
    @Override
    public boolean insert(CourseType entity) {
        super.insert(entity);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        courseTypeCache.del();

        //后台数据发生改变后，我们主页也要改变
        staticIndex();
        return true;
    }

    //缓存需要同步更新
    @Override
    public boolean deleteById(Serializable id) {
        super.deleteById(id);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        courseTypeCache.del();
        //后台数据发生改变后，我们主页也要改变
        staticIndex();
        return true;
    }

    //缓存需要同步更新
    @Override
    public boolean updateById(CourseType entity) {
        super.updateById(entity);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        courseTypeCache.del();
        //后台数据发生改变后，我们主页也要改变
        staticIndex();
        return true;
    }

    public void staticIndex(){
        //页面静态  模板+数据
        List<CourseType> courseTypes = this.queryTreeData();
        Map<String,Object> params = new HashMap<>();
        params.put("staticRoot","E:\\ideaworkspace\\hrm_parent\\hrm_course_parent\\hrm_course_service_2030\\src\\main\\resources\\home\\");
        params.put("courseTypes",courseTypes);
        VelocityUtils.staticByTemplate(params,"E:\\ideaworkspace\\hrm_parent\\hrm_course_parent\\hrm_course_service_2030\\src\\main\\resources\\home\\home.vm",
                "E:\\ideaworkspace\\hrm_web_parent\\hrm_web_course\\index.html");
    }
}
